/*******************************************************************************
 * Copyright (c) 2012 Till Kolditz.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 * created on 17.10.2012 at 15:41:13
 * 
 *  Contributors:
 *      Till Kolditz
 *******************************************************************************/
package de.cc.yFilesParser.wizard;

import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;

/**
 * Check the GraphML source file for used node styles. When there are several ones, it may be desired to distinguish
 * e.g. between class-nodes and attribute-nodes.
 * 
 * @author Till Kolditz - Till.Kolditz@GoogleMail.com
 */
public class CheckGraphmlSourceRunnable extends GraphMLRunnable implements IRunnableWithProgress
{
    private Set<String> nodeStyles = null;
    private Set<String> edgeValues = null;

    public CheckGraphmlSourceRunnable(ConvertWizard wizard)
    {
        super(wizard);
    }

    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException
    {
        super.run(monitor);

        monitor.beginTask("Inspect GraphML source file", IProgressMonitor.UNKNOWN);

        try
        {
            createReader(wizard.startPage.getSourceFile());

            monitor.subTask("Parsing source document");
            String nodegraphicID = null;
            nodeStyles = new HashSet<String>();
            edgeValues = new HashSet<String>();

            while (reader.hasNext())
            {
                switch (reader.next())
                {
                    case XMLStreamReader.START_ELEMENT:
                        if (reader.hasName())
                        {
                            String nodeName = reader.getName().getLocalPart().trim();
                            if ("key".equals(nodeName))
                            {
                                Key key = parseKey("node", "nodegraphics");
                                if (key != null)
                                    nodegraphicID = key.attrId;
                            }
                            else
                                if ("node".equals(nodeName))
                                {
                                    Node node = parseNode(nodegraphicID);
                                    nodeStyles.add(node.shape);
                                }
                                else
                                    if ("edge".equals(nodeName))
                                    {
                                        parseEdge();
                                    }
                        }
                        break;
                }
                if (monitor.isCanceled())
                    return;
            }
        }
        catch (InvocationTargetException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            openErrorDialog(e);
            // pass on the exception
            throw new InvocationTargetException(e);
        }
        finally
        {
            close();
        }

        monitor.done();
    }

    /**
     * @throws XMLStreamException
     */
    private void parseEdge() throws XMLStreamException
    {
        monitor.subTask("parsing \"edge\"");
        while (reader.hasNext())
        {
            switch (reader.next())
            {
                case XMLStreamReader.START_ELEMENT:
                    String name = reader.getLocalName();
                    if ("EdgeLabel".equals(name))
                    {
                        boolean doContinue = true;
                        while (doContinue && reader.hasNext())
                        {
                            switch (reader.next())
                            {
                                case XMLStreamConstants.START_ELEMENT:
                                    doContinue = false;
                                    break;
                                case XMLStreamConstants.CHARACTERS:
                                    // takes the very first characters event as the node's name
                                    edgeValues.add(reader.getText());
                                    doContinue = false;
                                    break;
                                case XMLStreamConstants.END_ELEMENT:
                                    doContinue = false;
                                    break;
                            }
                        }
                    }
                    break;
            }
            if (monitor.isCanceled())
                return;
        }
    }

    /**
     * Returns the actual list. Clients are advised not to change it.
     * 
     * @return the found node styles.
     */
    public Set<String> getNodeStyles()
    {
        return nodeStyles;
    }

    public Set<String> getEdgeValues()
    {
        return edgeValues;
    }
}
